package main

import (
	"fmt"
	"net/http"
	"reflect"
	"strings"

	"github.com/go-playground/locales/en"

	"github.com/go-playground/locales/zh"

	"github.com/gin-gonic/gin/binding"
	ut "github.com/go-playground/universal-translator"
	"github.com/go-playground/validator/v10"
	en_translations "github.com/go-playground/validator/v10/translations/en"
	zh_translations "github.com/go-playground/validator/v10/translations/zh"

	"github.com/gin-gonic/gin"
)

type SignUpForm struct {
	Age        uint8  `forms:"age" json:"age" binding:"gte=10,lte=130"`
	Name       string `forms:"name" json:"name" binding:"required,min=3"`
	Email      string `forms:"email" json:"email" binding:"required,email"`
	Password   string `forms:"password" json:"password" binding:"required"`
	RePassword string `forms:"repassword" json:"repassword" binding:"required,eqfield=Password"` // 跨字段验证
}

var trans ut.Translator

func removeTopStruct(fields map[string]string) map[string]string {
	res := map[string]string{}
	for field, err := range fields {
		res[field[strings.Index(field, ".")+1:]] = err
	}
	return res
}

func InitTrans(locale string) error {
	if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
		// 注册一个获取json的tag的自定义方法
		v.RegisterTagNameFunc(func(field reflect.StructField) string {
			name := strings.SplitN(field.Tag.Get("json"), ",", 2)[0]
			if name == "-" {
				return ""
			}
			return name
		})

		zhT := zh.New()              // 中文翻译器
		enT := en.New()              // 英文翻译器
		uni := ut.New(enT, zhT, enT) // 一个参数是备用的语言环境, 后面的才是应该支持的语言环境

		trans, ok = uni.GetTranslator(locale)
		if !ok {
			return fmt.Errorf("uni.GetTranslator(%s) error", locale)
		}

		switch locale {
		case "en":
			_ = en_translations.RegisterDefaultTranslations(v, trans)
		case "zh":
			_ = zh_translations.RegisterDefaultTranslations(v, trans)
		default:
			_ = en_translations.RegisterDefaultTranslations(v, trans)
		}
	}
	return nil
}

func main() {
	err := InitTrans("zh")
	if err != nil {
		fmt.Println("初始化翻译器错误")
		return
	}

	router := gin.Default()

	router.POST("/signup", func(c *gin.Context) {
		var signupForm SignUpForm
		err := c.ShouldBind(&signupForm)
		if err != nil {
			errs, ok := err.(validator.ValidationErrors)
			if !ok {
				c.JSON(http.StatusOK, gin.H{
					"msg": err.Error(),
				})
				return
			}

			c.JSON(http.StatusBadRequest, gin.H{
				"error": removeTopStruct(errs.Translate(trans)),
			})
			return
		}

		c.JSON(http.StatusOK, gin.H{
			"msg": "注册成功",
		})
	})

	_ = router.Run()
}
